package cn.aezo.minions.utils;

import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by smalle on 2017/11/8.
 */
public class SmUtils {
    /**
     * 根据classpath获取文件
     * @param relativePath 相对classpath的路径, 开头不需要/
     * @return
     */
    public static File getFileByClasspath(String relativePath) {
        URL url = SmUtils.class.getClassLoader().getResource(relativePath);
        if(url == null) return null;

        File file = new File(url.getFile());
        return file;
    }

    /**
     * 创建目录(包含目录是否存在判断) TODO
     * @param dirPath 绝对路径
     */
    public static void mkdir(String dirPath) {
        File root = new File(dirPath);
        if(root.exists()) {
            if (!root.isDirectory()) {
                throw new RuntimeException("目录被占用");
            }
        } else {
            root.mkdirs(); // mkdirs(可自动创建子目录) 和 mkdir
        }
    }

    /**
     * 创建多个目录
     * @param rootDir 根目录(结尾不含"/")
     * @param dirName 目录名称(开头不含"/")
     */
    public static void mkdirs(String rootDir, String... dirName) {
        for (String dir : dirName) {
            File root = new File(rootDir + "/" + dir);
            if(root.exists()) {
                if (!root.isDirectory()) {
                    throw new RuntimeException("目录被占用");
                }
            } else {
                root.mkdir();
            }
        }
    }

    /**
     * 复制文件
     * @param fromFile
     * @param toFile
     * @throws IOException
     */
    public static void copyFile(File fromFile, File toFile) throws IOException {
        FileInputStream ins = new FileInputStream(fromFile);
        FileOutputStream out = new FileOutputStream(toFile);
        byte[] b = new byte[1024];
        int n = 0;
        while((n=ins.read(b))!=-1){
            out.write(b, 0, n);
        }

        ins.close();
        out.close();
    }

    /**
     * TODO
     * MultipartFile 转 File
     * 会在系统临时目录产生临时文件，使用完后可删除
     * @param file
     * @throws Exception
     */
    public static File multipartFileToFile(MultipartFile file) throws Exception {
        File toFile = null;
        if(file.equals("")|| file.getSize()<=0) {
            file = null;
        } else {
            InputStream ins = null;
            ins = file.getInputStream();
            toFile = new File(System.getProperty("java.io.tmpdir") + "/" + file.getOriginalFilename());
            inputStreamToFile(ins, toFile);
            ins.close();
        }
        return toFile;
    }

    public static void inputStreamToFile(InputStream ins, File file) {
        try {
            OutputStream os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            ins.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取文件内容 TODO
     * @param fileOrName
     * @param keepFormat 是否保留格式(换行符)
     * @return
     * @throws IOException
     */
    public static String read(Object fileOrName, boolean keepFormat) throws IOException {
        File file = fileOrName instanceof String ? new File((String) fileOrName) : (File) fileOrName;
        if(keepFormat) {
            FileInputStream inputStream = null;
            try {
                inputStream = new FileInputStream(file);
                byte[] b = new byte[inputStream.available()];
                inputStream.read(b);
                return new String(b);
            } finally {
                close(inputStream);
            }
        } else {
            StringBuffer buffer = new StringBuffer();
            BufferedReader reader = null;
            try {
                reader = new BufferedReader(new FileReader(file));
                String tempString = null;
                // 一次读入一行，直到读入null为文件结束
                while ((tempString = reader.readLine()) != null) {
                    buffer.append(tempString);
                }
            } finally {
                close(reader);
            }

            return buffer.toString();
        }
    }

    public static void close(Closeable... closeables) {
        if(closeables == null) return;
        for (Closeable closeable: closeables) {
            try {
                if(closeable != null)
                    closeable.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 递归删除目录下的所有文件及子目录下所有文件 TODO
     * @param dir 将要删除的文件目录
     */
    public static boolean deleteDir(File dir) {
        if (dir.isDirectory()) {
            String[] children = dir.list();
            if(children != null) {
                for (String item : children) {
                    boolean success = deleteDir(new File(dir, item));
                    if (!success) {
                        return false;
                    }
                }
            }
        }
        // 目录此时为空，可以删除
        return dir.delete();
    }

    /**
     * TODO
     * @param fileOrPath
     * @param content
     * @param append
     * @throws IOException
     */
    public static void write(Object fileOrPath, String content, boolean append) throws IOException {
        BufferedWriter writer = null; // FileWriter容易产生乱码
        try {
            if(fileOrPath instanceof String) {
                fileOrPath = new File((String) fileOrPath);
            }
            File file = (File) fileOrPath;
            File fileP = file.getParentFile();
            if(!fileP.exists()) {
                fileP.mkdir();
            }
            writer = new BufferedWriter (new OutputStreamWriter(new FileOutputStream(file, append),"UTF-8"));
            writer.write(content);
        }  finally {
            close(writer);
        }
    }

    /**
     * 递归数据 TODO 参考TreeParse，level添加default方法
     * @param dbList
     * @param parentId
     * @param idName
     * @param pidName
     * @return
     */
    public static List<Map<String, Object>> getLevelData(List<Map<String, Object>> dbList, String parentId, String idName, String pidName) {
        List<Map<String, Object>> resultList = new ArrayList<>();
        for (Map<String, Object> data : dbList) {
            if (String.valueOf(parentId).equals(String.valueOf(data.get(pidName)))) {
                List<Map<String, Object>> childList = getLevelData(dbList, String.valueOf(data.get(idName)), idName, pidName);
                data.put("children", childList);
                resultList.add(data);
            }
        }
        return resultList;
    }

    public static String toUpperCaseFirst(String string) {
        char[] methodName = string.toCharArray();
        methodName[0] = Character.toUpperCase(methodName[0]);
        return String.valueOf(methodName);
    }
}
